﻿using Grpc.Core;
using Grpc.Core.Interceptors;
using RSTAi.Platform.GrpcService.Common;
using RSTAi.Platform.GrpcService.Services;

namespace RSTAi.Platform.GrpcService.Models
{
    public class TokenValidationInterceptor : Interceptor
    {
        private readonly ILogger<TokenValidationInterceptor> _logger;

        public TokenValidationInterceptor(ILogger<TokenValidationInterceptor> logger)
        {
            // _logger = loggerFactory.CreateLogger<TokenValidationInterceptor>();
            _logger = logger;
        }

        /// <summary>
        /// 统一进行token验证，一元方式
        /// </summary>
        /// <typeparam name="TRequest"></typeparam>
        /// <typeparam name="TResponse"></typeparam>
        /// <param name="request"></param>
        /// <param name="context"></param>
        /// <param name="continuation"></param>
        /// <returns></returns>
        public override async Task<TResponse> UnaryServerHandler<TRequest, TResponse>(
        TRequest request,
        ServerCallContext context,
        UnaryServerMethod<TRequest, TResponse> continuation)
        {
            _logger.LogInformation("Starting receiving call. Type/Method: {Type} / {Method}",
                MethodType.Unary, context.Method);
            try
            {
                if (context.Method != "/JwtTokenService.IJwtTokenServices/GetToken")
                {
                    string message = string.Empty;
                    if (!VerificationAuthorization(context, out message))
                    {
                        Type response = typeof(TResponse);
                        
                        if (response == typeof(ResponeDto))
                        {
                            var dto = new ResponeDto();
                            dto.Code = 110;
                            dto.Message = message;
                            dto.IsSuccess = false;
                            return (TResponse)(Object)dto;
                        }
                        else if (response == typeof(ResponeProductDto))
                        {
                            var dto = new ResponeProductDto();
                            dto.Code = 110;
                            dto.Message = message;
                            dto.IsSuccess = false;
                            return (TResponse)(Object)dto;
                        }
                        else if (response == typeof(ResponeProductStepDto))
                        {
                            var dto = new ResponeProductStepDto();
                            dto.Code = 110;
                            dto.Message = message;
                            dto.IsSuccess = false;
                            return (TResponse)(Object)dto;
                        }
                        else if (response == typeof(ResponeCurrentOrderDto))
                        {
                            var dto = new ResponeCurrentOrderDto();
                            dto.Code = 110;
                            dto.Message = message;
                            dto.IsSuccess = false;
                            return (TResponse)(Object)dto;
                        }
                        else if (response == typeof(ResponeCurrentOrderDto))
                        {
                            var dto = new ResponeCurrentOrderDto();
                            dto.Code = 110;
                            dto.Message = message;
                            dto.IsSuccess = false;
                            return (TResponse)(Object)dto;
                        }
                       
                        return await continuation(request, context);

                    }
                }

                return await continuation(request, context);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"Error thrown by {context.Method}.");
                throw;
            }
        }

        public override AsyncClientStreamingCall<TRequest, TResponse> AsyncClientStreamingCall<TRequest, TResponse>(ClientInterceptorContext<TRequest, TResponse> context, AsyncClientStreamingCallContinuation<TRequest, TResponse> continuation)
        {
            return base.AsyncClientStreamingCall(context, continuation);
        }

        public override AsyncServerStreamingCall<TResponse> AsyncServerStreamingCall<TRequest, TResponse>(TRequest request, ClientInterceptorContext<TRequest, TResponse> context, AsyncServerStreamingCallContinuation<TRequest, TResponse> continuation)
        {
            return base.AsyncServerStreamingCall(request, context, continuation);
        }

        public override Task DuplexStreamingServerHandler<TRequest, TResponse>(IAsyncStreamReader<TRequest> requestStream, IServerStreamWriter<TResponse> responseStream, ServerCallContext context, DuplexStreamingServerMethod<TRequest, TResponse> continuation)
        {
            return base.DuplexStreamingServerHandler(requestStream, responseStream, context, continuation);
        }

        Task WriteResponseHeadersAsync(StatusCode statusCode, string message, ServerCallContext context)
        {
            var httpContext = context.GetHttpContext();
            var errorMessage = message;
            var responseHeaders = new Metadata();
            context.Status = new Status(statusCode, errorMessage);//3) not working
            return context.WriteResponseHeadersAsync(responseHeaders);//4) alternative?
        }

        private bool VerificationAuthorization(ServerCallContext context, out string message)
        {
            message = string.Empty;
            var jwtToken = context.RequestHeaders.GetValue("authorization");
            if (string.IsNullOrEmpty(jwtToken))
            {
                message = "authorization cannot be empty!";
                return false;
            }
            string? cache_token = CacheHelper.GetCache<string>(jwtToken);
            if (string.IsNullOrEmpty(cache_token))
            {
                message = "authorization validate failed!";
                return false;

            }
            return true;
        }

        //private Task<TResponse> HadleResp<TResponse>( ServerCallContext context,string message)
        //{
        //    TResponse dto = null;
        //    if (context.Method.Contains("IAnalysisServices.IAnalysisServices"))
        //    {
        //        dto = response as ResponeOrderDateDto;
        //        dto.IsSuccess = false;
        //        dto.Code = 100;
        //        dto.Message = message;
        //    }


        //    return Task.FromResult(dto);


        //}
    

    }
}
